package com.cqhz.quwan.util

import com.blankj.utilcode.util.StringUtils
import com.cqhz.quwan.APP
import com.cqhz.quwan.common.KeyContract
import okhttp3.FormBody
import okhttp3.Interceptor
import okhttp3.RequestBody
import okhttp3.Response
import java.io.UnsupportedEncodingException
import java.net.URLDecoder
import java.nio.charset.Charset
import java.security.MessageDigest
import java.security.NoSuchAlgorithmException
import java.util.*
import kotlin.experimental.and


class GlobalRequestInterceptor : Interceptor {
    companion object {
        const val HEADER_NAME_SOURCE = "source"
        const val HEADER_NAME_APPKEY = "appKey"
        const val HEADER_NAME_CHANEL = "channel"
        const val HEADER_NAME_CITY = "city"
        const val HEADER_NAME_PHONE_MOBILE = "phoneModel"
        const val HEADER_NAME_EQUIPMENT = "equipmentId"
        const val HEADER_KEY_TIMESTAMP = "timestamp"//客户端时间戳
        const val HEADER_KEY_SIGNATURE = "signature"//签名信息
        const val PUBLIC_KEY = "040CD66A84025B94CEAC3EC1B49C92D0"
    }

    private var appKey: String? = null
    private var appSource: Int? = -1
    private var channel: String? = null
    private var phoneModel: String? = null
    private var equipment: String? = null

    init {
        appKey = APP.get()!!.getMetaDataVersion(KeyContract.APP_KEY)
        appSource = APP.get()!!.getMetaDataVersion(KeyContract.APP_SOURCE)
        channel = APP.channel
        phoneModel = "${APP.get()!!.getMobileBrand()} ${APP.get()!!.getMobileModel()}"
        equipment = APP.get()!!.getIMEI()
    }

    override fun intercept(chain: Interceptor.Chain): Response {
        val request = chain.request()
        val body: RequestBody = request.body()!!
        // 请求参数字典集合
        val paramsMap = HashMap<String, String>()
        if (body is FormBody) {
            for (i in 0 until body.size()) {
                // 加入请求参数集合
                paramsMap[body.encodedName(i)] = URLDecoder.decode(body.encodedValue(i), "UTF-8")
            }
        }
        val timeStamp = System.currentTimeMillis().toString()
        paramsMap[HEADER_NAME_APPKEY] = appKey ?: ""
        paramsMap[HEADER_NAME_SOURCE] = (appSource ?: -1).toString()
        paramsMap[HEADER_NAME_CHANEL] = channel ?: ""
        if (!StringUtils.isEmpty(APP.latitude) && !StringUtils.isEmpty(APP.longitude)) {
            paramsMap[HEADER_NAME_CITY] = APP.latitude + "," + APP.longitude
        }
        paramsMap[HEADER_NAME_PHONE_MOBILE] = phoneModel ?: ""
        paramsMap[HEADER_NAME_EQUIPMENT] = equipment ?: ""
        paramsMap[HEADER_KEY_TIMESTAMP] = timeStamp
        val signString = signString(paramsMap)
        paramsMap[HEADER_KEY_SIGNATURE] = signString
        val formBody = createNewFormBody(paramsMap)
        val newRequestBuilder = request.newBuilder()
        val newRequest = newRequestBuilder.method(request.method(), formBody).build()
        return chain.proceed(newRequest)
    }


    private fun createNewFormBody(params: Map<String, String>): FormBody {
        val formBody = FormBody.Builder()
        for (k in params.keys) {
            val v = params[k] ?: ""
            if (v.isNotEmpty()) {
                formBody.addEncoded(k, v)
            }
        }
        return formBody.build()
    }

    private fun signString(params: Map<String, String>): String {
        // 取参数字典排序后的值
        val paramsString = getParamStr(params)
        return Md5Util.encryption(PUBLIC_KEY + Md5Util.encryption(paramsString).toUpperCase())
    }

    /**
     * @param string 需要加密的字符串
     * @return 加密后的字符串
     */
    private fun doMD5(string: String): String {
        val hash: ByteArray
        try {
            hash = MessageDigest.getInstance("MD5").digest(string.toByteArray(charset("UTF-8")))
        } catch (e: NoSuchAlgorithmException) {
            e.printStackTrace()
            return ""
        } catch (e: UnsupportedEncodingException) {
            e.printStackTrace()
            return ""
        }

        val hex = StringBuilder(hash.size * 2)
        for (b in hash) {
            if (b and 0xFF.toByte() < 0x10) {
                hex.append("0")
            }
            hex.append(Integer.toHexString((b and 0xFF.toByte()).toInt()))
        }

        return hex.toString()
    }

    private fun getParamStr(params: Map<String, String>): String {
        val sb = StringBuilder()
        val paramsKeys = ArrayList(params.keys)
        paramsKeys.sort()
        for (key in paramsKeys) {
            if (!key.startsWith("text") && !key.startsWith("file") && !key.startsWith("unSign")) {
                try {
                    val v = params[key]
                    if (v?.isEmpty() == true) {
                        continue
                    }
                    sb.append(key).append("=").append(params[key]!!).append("&")
                } catch (e: Exception) {
                    e.printStackTrace()
                }

            }
        }
        if (sb.length > 1) {
            sb.deleteCharAt(sb.length - 1)
        }
        return sb.toString()
    }

    private fun convertCharset(charset: Charset): String {
        val s = charset.toString()
        val i = s.indexOf("[")
        return if (i == -1) s else s.substring(i + 1, s.length - 1)
    }
}